TK!2
=v
#1
:n
R
:v
'result
:s
i
#2
:n
a
:v
'x
:s
i
#3
:n
b
:v
'y
:s
i
#4
:n
c
:v
'temp1
:s
i
#5
:n
n
:v
4
:s
i
#6
:n
d
:v
'temp2
:s
i
#7
:n
P
:v
1.2345E15
:s
i
#8
:n
p
:v
'p
:s
i
=u
=l
#1
:n
a
:#
alint
:v
123456
123456123456
E
#2
:n
b
:#
alint
:v
121343565787
999999999999
E
#3
:n
c
:v
234
234567234567
567890567890
E
#4
:n
y
:#
alint
:v
456456
456456456456
456456456456
456456456456
E
#5
:n
x
:v
123
123123123123
123123123123
E
#6
:n
z
:v
E
#7
:n
temp1
:v
E
#8
:n
temp2
:v
E
#9
:n
p
:v
1234
5E11
E
#10
:n
result
:v
E
#11
:n
fact
:#
alint
:v
93
326215443944
152681699238
856266700490
715968264381
621468592963
895217599993
229915608941
463976156518
286253697920
827223758251
185210916864
0
0
E
=f
#1
:n
ALIadd
:c
ALI addition
:t
Procedure
:i
a,b,c
:o
z
#2
:n
ALIsubt
:c
ALI subtraction
:t
Procedure
:i
a,b,c
:o
z
#3
:n
ALImult
:c
ALI multiplication
:t
Procedure
:i
a,b,c
:o
z
#4
:n
ALIpower
:c
ALI exponentiation
:t
Procedure
:i
a,n,b
:o
z
#5
:n
ALIsum
:c
ALI summation
:t
Procedure
:i
a,b,c
#6
:n
ALIplus
:c
ALI plus operation
:t
Procedure
:i
a,b,c
#7
:n
ALIminus
:c
ALI minus operation
:t
Procedure
:i
a,b,c
#8
:n
ALIGT
:c
ALI "Greater Than"
:t
Procedure
:i
a,b
:o
z
#9
:n
ALILT
:c
ALI "Less Than" 
:t
Procedure
:i
a,b
:o
z
#10
:n
RTOALI
:c
Conversion from real to ALI number
:t
Procedure
:i
x,A
:o
a
#11
:n
ALITOR
:c
Conversion from ALI to real number
:t
Procedure
:i
A
:o
z
#12
:n
ALIfactorial
:c
Factorial in ALI form
:t
Procedure
:i
n,A
:o
a
#1
:n
ALIadd
:z
" Notation:  a,b  names of addend lists
"            c,z  name of result list

" Supporting functions: ALIsum, ALIplus, ALIminus, ALIGT

" Description: Performs addition operation on ALI numbers.

call ALIsum(a,b,c)
z:= c
/E
E
#2
:n
ALIsubt
:z
" Notation:  a    name of minuend list
"            b    name of subtrahend list
"            c,z  name of result list

" Supporting functions: ALIsum, ALIplus, ALIminus, ALIGT

" Description: Performs subtraction operation on ALI numbers.

b[1]:= -b[1]
call ALIsum(a,b,c)
b[1]:= -b[1]
z:= c
/E
E
#3
:n
ALImult
:z
" Notation:  a,b  names of multiplicand lists
"            c,z  name of result (product) list

" Description: Performs multiplication operation on ALI numbers.

call blank(c)
sa:= sgn(a[1])
a[1]:= abs(a[1])
sb:= sgn(b[1])
b[1]:= abs(b[1])
La:= length(a)
Lb:= length(b)
for i=1 to La
   for j=1 to Lb
      (higha,lowa):= divide(a[i],1e6)
      (highb,lowb):= divide(b[j],1e6)
      (highmiddle,lowmiddle) := divide(lowa*highb+higha*lowb,1e6)
      k:= i + j

      (carry,c[k]):= divide(elt(c,k,0)+lowa*lowb+lowmiddle*1e6,1e12)

      carry:= carry + highmiddle + higha*highb
A:    k:= k-1
      (carry,c[k]):= divide(elt(c,k,0)+carry,1e12)
      if and(carry<>0,k>1) goto A
   next j
next i
if c[1]<>0 goto END
call listcopy(c,c,2)
call blank(c,length(c))
END: a[1]:= sa*a[1]
     b[1]:= sb*b[1]
     if sa*sb<0 then c[1]:= -c[1]
     z:= c
/E
E
#4
:n
ALIpower
:z
" Notation:  a    name of basis list
"            n    exponent (positive integer)
"            b,z  name of result list (power)

" Supporting function: ALImult

" Description: Performs exponentiation operation on ALI basis.

call blank(b)
call listcopy(a,b)
for i=2 to n
   call listcopy(b,'aux)
   call ALImult(a,'aux,b;b)
next i
call delete('aux)
END: z:= b
/E
E
#5
:n
ALIsum
:z
" Notation:  a,b  names of summand lists
"            c    name of result list

" Supporting functions: ALIplus, ALIminus, ALIGT

" Description: Performs summation operation on ALI numbers.

call blank(c)
if sgn(a[1])*sgn(b[1])<0 goto A
if a[1]<0 goto F
call ALIplus(a,b,c)
return

F: a[1]:= -a[1]
b[1]:= -b[1]
call ALIplus(a,b,c)
a[1]:= -a[1]
b[1]:= -b[1]
c[1]:= -c[1]
return

A: k:= 2*sgn(a[1]) + sgn(b[1])
a[1]:= abs(a[1])
b[1]:= abs(b[1])
if ALIGT(b,a) goto B
call ALIminus(a,b,c)
c[1]:= k*c[1]
goto C

B: call ALIminus(b,a,c)
c[1]:= -k*c[1]

C: if k=1 then b[1]:= -b[1]  else a[1]:= -a[1]
/E
E
#6
:n
ALIplus
:z
" Notation:  a,b  names of addend lists
"            c    name of result list

" Desription: Adds two positive ALI numbers.  Should be used only when
"             called from ALIsum.

La:= length(a)
Lb:= length(b)
if La>=Lb goto A
(a,b):= (b,a)
(La,Lb):= (Lb,La)
A: j:= Lb
carry:= 0
for i=La to 1 step -1
   c[i]:= a[i] + elt(b,j,0) + carry
   carry:= c[i]>=1e12
   if carry then c[i]:= c[i] - 1e12
   j:= j - 1
next i
if not(carry) return
for i=La to 1 step -1
   c[i+1]:= c[i]
next i
c[1]:= 1
/E
E
#7
:n
ALIminus
:z
" Notation:  a  name of minuend list
"            b  name of subtrahend list
"            c  name of result list

" Description: Subtracts a smaller positive ALI number from a larger 
"              positive ALI number.  Should be used only when called
"              from ALIsum.

call blank(c)
La:= length(a)
Lb:= length(b)
call blank('maux)
call listcopy(a,'maux)
j:= Lb
carry:= 0
for i=La to 1 step -1
   if not(carry) goto A
   'maux[i]:= 'maux[i] - 1
   carry:= 0
A: if 'maux[i]>=elt(b,j,0) goto B
   'maux[i]:= 'maux[i] + 1e12
   carry:= 1
B: c[i]:= 'maux[i] - elt(b,j,0)
   j:= j - 1
next i
for k=1 to La
   if c[k]>0 goto C
next k
C: if k=1 goto END
j:= 0
for i=k to La
   j:= j + 1
   c[j]:= c[i]
next i
for i=j+1 to La
   call blank(c,i)
next i
END: call delete('maux)
/E
E
#8
:n
ALIGT
:z
" Notation:  a,b  names of lists with compared ALI numbers
"            z    result:  1 (true) or  0 (false)    

" Description: Compares two ALI numbers and returns  1  if the 1st ALI
"              number is greater than the 2nd, or  0  if it is not.

La:= length(a)
z:= sgn(La-length(b))
if z<>0 goto END
for i=1 to La
   z:= sgn(a[i]-b[i])
   if z<>0 goto END
next i
END: z:= max(z,0)
/E
E
#9
:n
ALILT
:z
" Notation:  a,b  names of lists with compared ALI numbers
"            z    result:  1 (true) or  0 (false)    

" Description: Compares two ALI numbers and returns  1  if the 1st ALI
"              number is less than the 2nd, or  0  if it is not.

La:= length(a)
z:= sgn(length(b)-La)
if z<>0 goto END
for i=1 to La
   z:= sgn(b[i]-a[i])
   if z<>0 goto END
next i
END: z:= max(z,0)
/E
E
#10
:n
RTOALI
:z
" Notation:  x    real (TK floating point) number
"            A,a  name of target list

" Description: Conversion of real number to Arbitrary Length Integer number.

call blank(A)
if abs(x)>999999999999.5 goto conversion
A[1]:= int(x)
goto end
conversion:
(n,m):= divide(int(log(abs(x))),12)
k:= 1 + (m<12) + (m<4)
for i=1 to n+1
   if i<=k then (A[i],x):= divide(x,10^(12*(n+1-i)))  else A[i]:= 0
   if i=k then A[i]:= round(A[i]+(2*x>10^(12*(n+1-i))),10^mod(9+m,12))
next i
if x<0 then A[1]:= -A[1]
end: a:= A
/E
E
#11
:n
ALITOR
:z
" Notation:  A  list with ALI number
"            z  real number approximation of A

" Description: Conversion of Arbitrary Length Integer number to real number.

n:= length(A)
z:= A[1]
for i=2 to min(n,3)
   z:= A[i] + z*1e12
next i
z:= z*10^(12*max(0,n-3))
/E
E
#12
:n
ALIfactorial
:z
" Notation:  n    argument (real number)
"            A,a  name of result list in ALI form 

" Description: Evaluates factorial  n!  in ALI form (n is limited only by
"              maximum list length).
x:= 1
for i=2 to min(n,21)
   x:= i * x
next i
a:= RTOALI(x,A)
if n<22 return
for i=22 to n
   call listcopy(A,'aux)
   A:= ALImult(RTOALI(i,'I),'aux,A)
next i
call delete('aux)
call delete('I)
/E
E
=r
#1
:r
" Introduction to TK Arbitrary Length Integer Arithmetic
:s
C
#2
:r
" -------------------------------------------------------
:s
C
#3
:r
" All numerical values in TK are represented by floating point numbers with
:s
C
#4
:r
" 16 significant digits.  The smallest non-zero number is approximately
:s
C
#5
:r
" 1e-307, the largest is 1e308 (see model LIMITS in the UTIL subdirectory). 
:s
C
#6
:r
" This is quite generous for most technical and other computations.  Yet,
:s
C
#7
:r
" sometimes you want to work with very large numbers and/or you want to carry
:s
C
#8
:r
" your calculations to a larger number of significant digits.
:s
C
#9
:r
" The TK Arbitrary Length Integer (ALI) package offers a set of procedures
:s
C
#10
:r
" that you can combine and use for experimentation and work with large 
:s
C
#11
:r
" numbers.  This set of ALI procedures was developed to fit the current TK
:s
C
#12
:r
" environment rather than the other way around.  Consequently, they are
:s
C
#13
:r
" rather slow and should be considered only as a supplement to other TK
:s
C
#14
:r
" features.
:s
C
#16
:r
" ALI numbers are represented by lists of elements with up to 12 digit
:s
C
#17
:r
" numbers each.  For instance, the list representation of a 40-digit integer
:s
C
#18
:r
" number
:s
C
#19
:r
"               2736482095486573000076239450650698738549
:s
C
#20
:r
"
:s
C
#21
:r
" will be as follows:                2,736
:s
C
#22
:r
"                          482,095,486,573
:s
C
#23
:r
"                               76,239,450
:s
C
#24
:r
"                          650,698,738,549
:s
C
#26
:r
" It is convenient to insert and display the ALI numbers in the Interactive
:s
C
#27
:r
" Tables, and to use a numeric format with Numeric Notation set to  Decimal
:s
C
#28
:r
" and Digit Grouping Symbol set to  ,  (see the Numeric Format Subsheet for
:s
C
#29
:r
" the format 'alint' used with this ALI package).
:s
C
#30
:r
"
:s
C
#31
:r
" Leading zeros in the 12-digit segments are not displayed, and a list
:s
C
#32
:r
" element representing 12 zeros displays just one zero.  Negative ALI numbers
:s
C
#33
:r
" are distinguished by the first list element being negative.  
:s
C
#35
:r
" When inputting ALI numbers in a List Subsheet or in an Interactive Table
:s
C
#36
:r
" (with field width 17), make sure that
:s
C
#37
:r
"     no list element is negative (except, optionally, the first),
:s
C
#38
:r
"     all elements have integer values between  0  and  999,999,999,999
:s
C
#39
:r
"      (don't insert the grouping symbols yourself when you type an entry --
:s
C
#40
:r
"      the 'alint' format will cause them to be inserted automatically).
:s
C
#42
:r
" The arithmetic and other operations on ALI numbers are performed by calling
:s
C
#43
:r
" or referring to appropriate procedures.  The procedure arguments are list
:s
C
#44
:r
" names.  For instance, in order to multiply two numbers represented by lists
:s
C
#45
:r
" x  and  y , and to deposit the results in a list  z , you write a rule
:s
C
#46
:r
"
:s
C
#47
:r
call ALImult('x,'y,'z;'z)      " ONE "
:s
C
#48
:r
"
:s
C
#49
:r
" Uncancel this rule, bring up table 'one', press F9 and watch how the
:s
C
#50
:r
" product is generated.
:s
C
#52
:r
" The output argument used in the ALI procedures copies the name of the
:s
C
#53
:r
" result list (such as 'z above).  Thanks to this somewhat artificial
:s
C
#54
:r
" convention we can nest the references to ALI procedures in a similar way
:s
C
#55
:r
" as in ordinary rules, and use the Variable Sheet for assigning list names.
:s
C
#56
:r
" For instance,
:s
C
#57
:r
"
:s
C
#58
:r
R = ALImult(ALIpower(ALIadd(a,b,c),n,d),RTOALI(P,p),R)    " TWO "
:s
C
#59
:r
"
:s
C
#60
:r
"stands for
:s
C
#61
:r
"                                  n
:s
C
#62
:r
"                R   =  { ( a + b )   } p
:s
C
#63
:r
"
:s
C
#64
:r
" intermediate variables  c=a+b  and  d=c^n; all variables  a,b,c,d,n,p,P,R
:s
C
#65
:r
" appear in the Variable Sheet.  The variables  a,b,c,d,R  must be assigned
:s
C
#66
:r
" symbolic values, and lists specified by  a  and  b  must be filled with
:s
C
#67
:r
" numeric values.  Input values  n  and  P  are to be assigned directly on
:s
C
#68
:r
" the Variable Sheet:  n  because the function ALIpower works with integer-
:s
C
#69
:r
" valued real number exponents and  P  because the function  RTOALI  converts
:s
C
#70
:r
" it into an ALI number and sends it to a list specified by the symbolic
:s
C
#71
:r
" value of the variable  p .
:s
C
#73
:r
" The contents of the Variable Sheet and table 'two' should make clear the
:s
C
#74
:r
" connections between the Rule Sheet, Variable Sheet, lists with the ALI
:s
C
#75
:r
" numbers and procedure actions.  (Cancel rule "ONE", uncancel rule "TWO",
:s
C
#76
:r
" bring up table "two", and press F9.)
:s
C
#78
:r
" In the last exercise in this introduction we will utilize the ALI facili-
:s
C
#79
:r
" ties for evaluating factorials of very large arguments.  The procedure to
:s
C
#80
:r
" use is stored under the name ALIfactorial.  Look at its Function Subsheet
:s
C
#81
:r
" and then bring up table 'three' where you can watch how the factorial is
:s
C
#82
:r
" being built up.  You can use the  / E E  command and specify 
:s
C
#83
:r
" ALIfactorial(n,'fact) as an expression, where  n  is the number whose
:s
C
#84
:r
" factorial you want to find.  (Large  n  may take a while:  the value for
:s
C
#85
:r
" 100! that comes up in table 'three' took about one minute on a 12MHz PC's
:s
C
#86
:r
" Limited 286 computer with a math co-processor.)
:s
C
#88
:r
" See the models ALI02 and ALI03 for the continuation of the ALI story.
:s
C
=p
=t
#1
:n
one
:s
Screen
:v
Vertical
:f
1
:r
""
:c
""
:t
""
:u
#1
:l
x
:n
alint
:w
17
:h
""
#2
:l
y
:n
alint
:w
17
:h
""
#3
:l
z
:n
alint
:w
17
:h
""
#4
:w
10
:h
""
E
#2
:n
two
:s
Screen
:v
Vertical
:f
1
:r
""
:c
""
:t
"                      ÄÄ Note: press [Tab] to see lists  x  and  y"
:u
#1
:l
p
:n
alint
:w
17
:h
""
#2
:l
result
:n
alint
:w
17
:h
""
#3
:l
temp1
:n
alint
:w
17
:h
""
#4
:l
temp2
:n
alint
:w
17
:h
""
#5
:l
x
:n
alint
:w
17
:h
""
#6
:l
y
:n
alint
:w
17
:h
""
E
#3
:n
three
:s
Screen
:v
Vertical
:f
1
:r
""
:c
""
:t
""
:u
#1
:l
fact
:n
alint
:w
17
:h
""
#2
:l
aux
:n
alint
:w
17
:h
""
#3
:l
I
:n
alint
:w
17
:h
""
E
=n
#1
:n
alint
:d
15
:f

:^
Decimal
:e
"."
:m
","
:c
ALI number format
:p
None
:j
Right
:s
- Only
:q
0
:x
0
:l
""
:t
""
:v
"0"
=g
#1
:c
.000001
:i
10
:v
Yes
:l
60
:f
66
:m
0
:w
80
:b
Yes
:a
Yes
:r
Yes
:h
No
:t
1
:n
Yes
:d
LPT1
%Tr,f,0,1,0,1,0
